﻿using QwLib;
using SCADA.Comm;
using SCADA.Drive;
using SIE.SCADA.Common.Log;
using SIE.SCADA.WebApi;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SIE.SCADA.ZemtDemo.Machines
{
    abstract class BaseMachine : ObservableObject, IDisposable, IBaseMachine
    {
        static readonly Dictionary<string, BaseComm> commResource = new Dictionary<string, BaseComm>();
        private readonly string configFile = AppDomain.CurrentDomain.BaseDirectory + "DeviceCfg.xml";

        public BaseProtocol BaseProtocol { get; set; }
        protected string IPAddress { get; set; }
        protected string _deviceID;
        protected string ApiAddr { get; set; }
        protected string ProcessNo { get; set; }

        public ObservableCollection<string> Msg { get; set; } = new ObservableCollection<string>();
        protected int Port { get; set; }
        System.Timers.Timer tm = new System.Timers.Timer(10 * 1000);  //如果连接状态断开10秒钟提醒一次
        public BaseMachine(string deviceID)
        {
            _deviceID = deviceID;
            XDocument xDocument = XDocument.Load(configFile);
            XElement element = xDocument.Descendants("Devices").Elements()
                .Where(t => t.Attribute("DeviceID").Value == deviceID).First();
            DeviceInit(element);
        }

        public void AddMsg(string msg)
        {
            //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            //{
            //    Msg.Add($"{DateTime.Now} {msg}");
            //}));
        }

        public void ClearMsg()
        {
            //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            //{
            //    Msg.Clear();
            //}));
        }

        private void DeviceInit(XElement node)
        {
            DeviceItem device = Util.Deserialize<DeviceItem>(node.ToString());
            if (!string.IsNullOrEmpty(device.Protocol))
            {
                //Assembly assembly = Assembly.Load("SCADA");
                Type protocolType = Assembly.GetExecutingAssembly().GetType(device.Protocol);
                BaseProtocol = (SMDCMachine)Activator.CreateInstance(protocolType,
                     null,
                     device.DeviceAddress);
                BaseProtocol.DeviceID = device.DeviceID;
                BaseProtocol.DeviceDesc = device.Desc;
                BaseProtocol.HeartHeatRegName = device.HeartHeatReg;
                ApiAddr = device.ApiAddr;
                ProcessNo = device.ProcessNo;

                if (Env.Devices != null)
                {
                    Env.Devices.Add(device.DeviceID, BaseProtocol);
                }

                if (Env.Machines != null)
                {
                    Env.Machines.Add(device.DeviceID, this);
                }

                var annotationsNode = node.Descendants("Annotations").FirstOrDefault();  //查询注释信息
                BaseProtocol.SetRegAnnotation(annotationsNode);

                BaseProtocol.ConnectStateChanged += ConnectStateChanged;
                BaseProtocol.RegValueChanged += RegValueChanged;

                if (!string.IsNullOrEmpty(device.ListenReg))
                {
                    Regex.Replace(device.ListenReg, @"[,|，|;|；]{1,}", ";");
                    BaseProtocol.BeginListen(device.ListenReg.Split(';').Select(t => t.Trim()).ToList(), device.PollRate);
                }
            }
            tm.Elapsed += Tm_Elapsed;
        }

        public BaseMachine(XElement node)
        {
            DeviceInit(node);
        }

        public void WriteMessage(string regName, params object[] @params)
        {
            if (BaseProtocol is SMDCMachine machine)
                machine.WriteMessage(regName, @params);
        }

        public void WriteFullName(string regName, params object[] @params)
        {
            if (BaseProtocol is SMDCMachine machine)
                machine.WriteFullName(regName, @params);
        }

        public ValueItem ReadTag(string regName)
        {
            if (BaseProtocol is SMDCMachine machine)
            {
                return machine.ReadTag(regName);
            }
            else
            {
                return new ValueItem();
            }
        }

        protected abstract void RegValueChanged(object sender, RegValueChangedEventArgs e);

        private void Tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {

            //ProgramMain.PrintErro($"{baseProtocol.Comm?.CommInfo} {baseProtocol.DeviceDesc} 连接失败");
        }

        protected void ConnectStateChanged(object sender, global::SCADA.ConnectStateChangedEventArgs e)
        {
            if (e.ConnectState == ConnectStates.Connected)
            {
                Logger.Info($"{BaseProtocol.Comm?.CommInfo} {BaseProtocol.DeviceDesc} 连接成功");
                tm.Enabled = false;
            }
            else
            {
                Logger.Error($"{BaseProtocol.Comm?.CommInfo} {BaseProtocol.DeviceDesc} 连接失败");
                tm.Enabled = true;
            }

            //Env.MESAPI.Request<MesResponse>(new MesApi.GetEquipmentStatusRequest(
            //                BaseProtocol.DeviceID,
            //                e.ConnectState == ConnectStates.Connected ? "正常" : "停机"
            //                ));
        }

        public virtual void Dispose()
        {
            if (BaseProtocol != null)
            {
                BaseProtocol.Dispose();
            }
        }

    }
}
